<style lang="scss">
	@import '../../assets/css/_variables.scss';
	@import '../../assets/css/_functions.scss';
	.swipe {
		overflow: hidden;
		position: relative;
		text-align: center;
		height: rem(250);
		background: #fff;
		.swipe-items-wrap {
			position: relative;
			overflow: hidden;
			height: 100%;
			.swipe-item {
				position: absolute;
				transform: translateX(-100%);
				display: none;
				text-align: center;
				width: rem(375);
				height: auto;
				img {
					width: rem(250);
					height: rem(250);
				}
				&.active {
					display: block;
					transform: none;
				}
			}
		}
		.swipe-indicators {
			position: absolute;
			bottom: 10px;
			left: 50%;
			transform: translateX(-50%);
			.swipe-indicator {
				display: inline-block;
				background: #000;
				margin: 0 3px;
				width: rem(3);
				height: rem(3);
				&.active {
					width: rem(6);
					height: rem(3);
					background: $_03a9f4;
				}
			}
		}
		.swipe-nums {
			position: absolute;
			background: rgba(51, 51, 51, 0.50);
			border-radius: rem(15);
			width: rem(37);
			height: rem(24);
			line-height: rem(24);
			font-size: rem(14);
			color: #fff;
			right: rem(10);
			bottom: rem(10);
		}
	}
	
	.pop-swiper {
		height: 100%;
		width: 100%;
		position: fixed;
		z-index: 10002;
		background: none;
		.swipe-items-wrap {
			position: fixed;
			left: 0;
			top: 50%;
			width: rem(375);
			transform: translateY(-50%);
			height: rem(250);
			background: #fff;
		}
		.swipe-nums {
			display: none;
		}
		.swipe-indicators {
			.swipe-indicator {
				opacity: 0.8;
				background: #ffffff;
				width: rem(7);
				height: rem(7);
				border-radius: 100%;
				&.active {
					background: #0299f6;
					width: rem(7);
					height: rem(7);
					border-radius: 100%;
				}
			}
		}
	}
	
	.swipe-model {
		position: fixed;
		width: 100%;
		height: 100%;
		background: #000;
		top: 0;
		z-index: 10001;
	}
</style>

<template>
	<div>
		<div class="swipe" :class="{'pop-swiper': isPopSwiper}" @click='popSwiper'>
			<div class="swipe-items-wrap" v-el:wrap>
				<slot></slot>
			</div>
			<div class="swipe-indicators" v-show="showIndicators">
				<div class="swipe-indicator" v-for="page in pages" :class="{ active: $index === index }"></div>
			</div>
			<div class="swipe-nums" v-show='showNums'>
				<span>{{index+1}}</span>/<span>{{pages.length}}</span>
			</div>

		</div>
		<div class="swipe-model" v-if='isPopSwiper' @click='swipeModelVisble'></div>
	</div>
</template>

<script type="text/ecmascript-6">
	import {
		once,
		addClass,
		removeClass
	} from 'wind-dom';

	export default {
		name: 'mt-swipe',

		created() {
			this.dragState = {};
		},

		data() {
			return {
				ready: false,
				dragging: false,
				userScrolling: false,
				animating: false,
				index: 0,
				pages: [],
				timer: null,
				reInitTimer: null,
				noDrag: false,
				isPopSwiper: false
			};
		},

		props: {
			speed: {
				type: Number,
				default: 300
			},

			auto: {
				type: Number,
				default: 3000
			},

			continuous: {
				type: Boolean,
				default: true
			},

			showIndicators: {
				type: Boolean,
				default: true
			},
			showNums: {
				type: Boolean,
				default: true
			},
			noDragWhenSingle: {
				type: Boolean,
				default: true
			},

			prevent: {
				type: Boolean,
				default: false
			}
		},

		events: {
			swipeItemCreated() {
				if(!this.ready) return;

				clearTimeout(this.reInitTimer);
				this.reInitTimer = setTimeout(() => {
					this.reInitPages();
				}, 100);
			},

			swipeItemDestroyed() {
				if(!this.ready) return;

				clearTimeout(this.reInitTimer);
				this.reInitTimer = setTimeout(() => {
					this.reInitPages();
				}, 100);
			}

		},

		methods: {
			popSwiper() {
				this.isPopSwiper = !this.isPopSwiper;
				this.showIndicators = !this.showIndicators;
			},
			swipeModelVisble() {
				this.isPopSwiper = false;
				alert('aaa');
			},
			translate(element, offset, speed, callback) {
				if(speed) {
					this.animating = true;
					element.style.webkitTransition = '-webkit-transform ' + speed + 'ms ease-in-out';
					setTimeout(() => element.style.webkitTransform = `translate3d(${offset}px, 0, 0)`, 50);

					var called = false;

					var transitionEndCallback = () => {
						if(called) return;
						called = true;
						this.animating = false;
						element.style.webkitTransition = '';
						element.style.webkitTransform = '';
						if(callback) {
							callback.apply(this, arguments);
						}
					};

					once(element, 'webkitTransitionEnd', transitionEndCallback);
					setTimeout(transitionEndCallback, speed + 100); // webkitTransitionEnd maybe not fire on lower version android.
				} else {
					element.style.webkitTransition = '';
					element.style.webkitTransform = `translate3d(${offset}px, 0, 0)`;
				}
			},

			reInitPages() {
				var children = this.$children;
				this.noDrag = children.length === 1 && this.noDragWhenSingle;

				var pages = [];
				this.index = 0;

				children.forEach(function(child, index) {
					pages.push(child.$el);

					removeClass(child.$el, 'active');

					if(index === 0) {
						addClass(child.$el, 'active');
					}
				});

				this.pages = pages;
			},

			doAnimate(towards, options) {
				if(this.$children.length === 0) return;
				if(!options && this.$children.length < 2) return;

				var prevPage, nextPage, currentPage, pageWidth, offsetLeft;
				var speed = this.speed || 300;
				var index = this.index;
				var pages = this.pages;
				var pageCount = pages.length;

				if(!options) {
					pageWidth = this.$el.clientWidth;
					currentPage = pages[index];
					prevPage = pages[index - 1];
					nextPage = pages[index + 1];
					if(this.continuous && pages.length > 1) {
						if(!prevPage) {
							prevPage = pages[pages.length - 1];
						}
						if(!nextPage) {
							nextPage = pages[0];
						}
					}
					if(prevPage) {
						prevPage.style.display = 'block';
						this.translate(prevPage, -pageWidth);
					}
					if(nextPage) {
						nextPage.style.display = 'block';
						this.translate(nextPage, pageWidth);
					}
				} else {
					prevPage = options.prevPage;
					currentPage = options.currentPage;
					nextPage = options.nextPage;
					pageWidth = options.pageWidth;
					offsetLeft = options.offsetLeft;
				}

				var newIndex;

				var oldPage = this.$children[index].$el;

				if(towards === 'prev') {
					if(index > 0) {
						newIndex = index - 1;
					}
					if(this.continuous && index === 0) {
						newIndex = pageCount - 1;
					}
				} else if(towards === 'next') {
					if(index < pageCount - 1) {
						newIndex = index + 1;
					}
					if(this.continuous && index === pageCount - 1) {
						newIndex = 0;
					}
				}

				var callback = () => {
					if(newIndex !== undefined) {
						var newPage = this.$children[newIndex].$el;
						removeClass(oldPage, 'active');
						addClass(newPage, 'active');

						this.index = newIndex;
					}

					if(prevPage) {
						prevPage.style.display = '';
					}

					if(nextPage) {
						nextPage.style.display = '';
					}
				};

				setTimeout(() => {
					if(towards === 'next') {
						this.translate(currentPage, -pageWidth, speed, callback);
						if(nextPage) {
							this.translate(nextPage, 0, speed);
						}
					} else if(towards === 'prev') {
						this.translate(currentPage, pageWidth, speed, callback);
						if(prevPage) {
							this.translate(prevPage, 0, speed);
						}
					} else {
						this.translate(currentPage, 0, speed, callback);
						if(typeof offsetLeft !== 'undefined') {
							if(prevPage && offsetLeft > 0) {
								this.translate(prevPage, pageWidth * -1, speed);
							}
							if(nextPage && offsetLeft < 0) {
								this.translate(nextPage, pageWidth, speed);
							}
						} else {
							if(prevPage) {
								this.translate(prevPage, pageWidth * -1, speed);
							}
							if(nextPage) {
								this.translate(nextPage, pageWidth, speed);
							}
						}
					}
				}, 10);
			},

			next() {
				this.doAnimate('next');
			},

			prev() {
				this.doAnimate('prev');
			},

			doOnTouchStart: function(event) {
				if(this.noDrag) return;

				var element = this.$el;
				var dragState = this.dragState;
				var touch = event.touches[0];

				dragState.startTime = new Date();
				dragState.startLeft = touch.pageX;
				dragState.startTop = touch.pageY;
				dragState.startTopAbsolute = touch.clientY;

				dragState.pageWidth = element.offsetWidth;
				dragState.pageHeight = element.offsetHeight;

				var prevPage = this.$children[this.index - 1];
				var dragPage = this.$children[this.index];
				var nextPage = this.$children[this.index + 1];

				if(this.continuous && this.pages.length > 1) {
					if(!prevPage) {
						prevPage = this.$children[this.$children.length - 1];
					}
					if(!nextPage) {
						nextPage = this.$children[0];
					}
				}

				dragState.prevPage = prevPage ? prevPage.$el : null;
				dragState.dragPage = dragPage ? dragPage.$el : null;
				dragState.nextPage = nextPage ? nextPage.$el : null;

				if(dragState.prevPage) {
					dragState.prevPage.style.display = 'block';
				}

				if(dragState.nextPage) {
					dragState.nextPage.style.display = 'block';
				}
			},

			doOnTouchMove: function(event) {
				if(this.noDrag) return;

				var dragState = this.dragState;
				var touch = event.touches[0];

				dragState.currentLeft = touch.pageX;
				dragState.currentTop = touch.pageY;
				dragState.currentTopAbsolute = touch.clientY;

				var offsetLeft = dragState.currentLeft - dragState.startLeft;
				var offsetTop = dragState.currentTopAbsolute - dragState.startTopAbsolute;

				var distanceX = Math.abs(offsetLeft);
				var distanceY = Math.abs(offsetTop);
				if(distanceX < 5 || (distanceX >= 5 && distanceY >= 1.73 * distanceX)) {
					this.userScrolling = true;
					return;
				} else {
					this.userScrolling = false;
					event.preventDefault();
				}
				offsetLeft = Math.min(Math.max(-dragState.pageWidth + 1, offsetLeft), dragState.pageWidth - 1);

				var towards = offsetLeft < 0 ? 'next' : 'prev';

				if(dragState.prevPage && towards === 'prev') {
					this.translate(dragState.prevPage, offsetLeft - dragState.pageWidth);
				}
				this.translate(dragState.dragPage, offsetLeft);
				if(dragState.nextPage && towards === 'next') {
					this.translate(dragState.nextPage, offsetLeft + dragState.pageWidth);
				}
			},

			doOnTouchEnd: function() {
				if(this.noDrag) return;

				var dragState = this.dragState;

				var dragDuration = new Date() - dragState.startTime;
				var towards = null;

				var offsetLeft = dragState.currentLeft - dragState.startLeft;
				var offsetTop = dragState.currentTop - dragState.startTop;
				var pageWidth = dragState.pageWidth;
				var index = this.index;
				var pageCount = this.pages.length;

				if(dragDuration < 300) {
					let fireTap = Math.abs(offsetLeft) < 5 && Math.abs(offsetTop) < 5;
					if(isNaN(offsetLeft) || isNaN(offsetTop)) {
						fireTap = true;
					}
					if(fireTap) {
						this.$children[this.index].$emit('tap');
					}
				}

				if(dragDuration < 300 && dragState.currentLeft === undefined) return;

				if(dragDuration < 300 || Math.abs(offsetLeft) > pageWidth / 2) {
					towards = offsetLeft < 0 ? 'next' : 'prev';
				}

				if(!this.continuous) {
					if((index === 0 && towards === 'prev') || (index === pageCount - 1 && towards === 'next')) {
						towards = null;
					}
				}

				if(this.$children.length < 2) {
					towards = null;
				}

				this.doAnimate(towards, {
					offsetLeft: offsetLeft,
					pageWidth: dragState.pageWidth,
					prevPage: dragState.prevPage,
					currentPage: dragState.dragPage,
					nextPage: dragState.nextPage
				});

				this.dragState = {};
			}
		},

		destroyed() {
			if(this.timer) {
				clearInterval(this.timer);
				this.timer = null;
			}
			if(this.reInitTimer) {
				clearTimeout(this.reInitTimer);
				this.reInitTimer = null;
			}
		},

		ready() {
			this.ready = true;

			if(this.auto > 0) {
				this.timer = setInterval(() => {
					if(!this.dragging && !this.animating) {
						this.next();
					}
				}, this.auto);
			}

			this.reInitPages();

			var element = this.$el;

			element.addEventListener('touchstart', (event) => {
				if(this.prevent) {
					event.preventDefault();
				}
				if(this.animating) return;
				this.dragging = true;
				this.userScrolling = false;
				this.doOnTouchStart(event);
			});

			element.addEventListener('touchmove', (event) => {
				if(!this.dragging) return;
				this.doOnTouchMove(event);
			});

			element.addEventListener('touchend', (event) => {
				if(this.userScrolling) {
					this.dragging = false;
					this.dragState = {};
					return;
				}
				if(!this.dragging) return;
				this.doOnTouchEnd(event);
				this.dragging = false;
			});
		}
	};
</script>